# 定义一个的序列化器用来处理绑定用户的功能
from django_redis import get_redis_connection
from rest_framework import serializers
from rest_framework.response import Response

from .models import OauthQQUser
from oauth.utils import get_openid
from users.models import User


class UserBindingSerializer(serializers.Serializer):
    # 获取需要校验的字段,密码,手机号,短信验证码以及access_token
    password = serializers.CharField(min_length=8, max_length=20, label='密码')
    mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$')
    sms_code = serializers.CharField(label='短信验证码')
    access_token = serializers.CharField(label='凭证')

    # 定义校验数据的方法
    def validate(self, attrs):
        # 获取openid,判断用户是否已经绑定了账号
        access_token = attrs['access_token']
        openid = get_openid(access_token)
        # 判断是否获取到openid密钥则抛出异常
        if not openid:
            raise serializers.ValidationError('access_token已失效')
        # 获取到openid将其存入字典中,在下一次访问时会直接去数据库中查找已经绑定的用户信息
        attrs['access_token'] = openid

        # 验证短信验证码的正确性
        mobile = attrs['mobile']
        sms_code = attrs['sms_code']
        # 建立redis数据库连接
        redis = get_redis_connection('verify')
        # 　在redis数据库中查找短信验证码
        real_smscode = redis.get('sms_%s' % mobile).decode()
        if real_smscode != sms_code:
            raise serializers.ValidationError('短信验证码错误')
        # 通过手机号在数据库中查找用户,可能获取不到,放入异常捕获中
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            pass
        else:
            # 用户存在,检查密码是否正确
            password = attrs['password']
            if not user.check_password(password):
                raise serializers.ValidationError('密码错误')

            attrs['user'] = user
        return attrs

    # 重写将用户信息保存到数据库表中的方法
    def create(self, validated_data):
        # 获取需要校验的用户数据
        user = validated_data.get('user')
        # 如果用户数据不存在,就新增用户到数据库的用户表中,并将openid和用户id关联起来,并且需要对密码进行加密,不然检查密码时会出现错误
        if user is None:
            user = User.objects.create(
                username=validated_data['mobile'],
                password=validated_data['password'],
                mobile=validated_data['mobile']

            )
            user.set_password(validated_data['password'])
            user.save()

        # 将用户和openid绑定
        OauthQQUser.objects.create(
            user=user,
            openid=validated_data['access_token']
        )
        # 向视图对象中补充user对象属性，以便在视图中使用user
        self.context['view'].user = user
        return user